package co.edu.udea.herbario.bb;

import co.edu.udea.herbario.bl.GeneracionLista;
import co.edu.udea.herbario.dto.Ejemplar;
import co.edu.udea.herbario.dto.Especie;
import co.edu.udea.herbario.dto.Familia;
import co.edu.udea.herbario.dto.Genero;
import co.edu.udea.herbario.util.ConstantesStatic;
import com.icesoft.faces.component.selectinputtext.SelectInputText;
import com.icesoft.faces.component.selectinputtext.TextChangeEvent;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import javax.faces.component.html.HtmlSelectOneRadio;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.model.SelectItem;
import com.icesoft.faces.context.effects.JavascriptContext;
import javax.faces.context.FacesContext;

/**
 * Esta clase contiene la implementacion de los metodos de busqueda de ejemplares
 *
 * @author Marcela Colorado
 */

public class ConsultaBean
{
    //datos de autocompletacion
    FamiliaBean familiaBean;
    GeneroBean generoBean;
    EjemplarBean ejm;
    
    private SelectInputText campoAutocompleta;
    private SelectInputText campoAutocompletaFamilia;
    private SelectInputText campoAutocompletaGenero;
    private SelectInputText campoAutocompletaNomCientifico;
    private List<SelectItem> listaResultados = new ArrayList<SelectItem>(); //lista de opciones desplegada
    private List<SelectItem> listaResultadosFamilia = new ArrayList<SelectItem>();
    ArrayList <String> familias;
    ArrayList <String> generos;
    ArrayList <String> nombresCientificos;
    int limiteDatos = 10;

   /**
    * Listener que se encarga de cambiar la lista de opciones cuando cambia el Input (campo de busqueda) en la
    * busqueda basica
    *
    * @param event
    *
    * @return "ok" indica que el proceso se realizó correctamente
    */
    public String actualizarListaOpcionesCampo(TextChangeEvent event) 
    {
        int auxopcion = Integer.parseInt(this.getOpcion().getValue().toString());
        try
        {
            actualizarListaOpciones(event.getNewValue(), auxopcion);
        }
        catch (NullPointerException e)
        {
            mensaje = "No se pudo acceder a la base de datos";
            JavascriptContext.addJavascriptCall(FacesContext.getCurrentInstance(),"mostrarMensajeBasica('"+mensaje+"');");
            return "fail";
        }
        FacesContext.getCurrentInstance().renderResponse(); //despues de actulizar la  lista renderiza la respuesta
        return "ok";
    }

    /**
     * Metodo que lista las sugerencias en el campo de busqueda
     *
     * @param value corresponde a la cadena de caracteres ingresada en el campo de busqueda
     * @param opcion corresponde al filtro de busqueda seleccionado: familia, genero o nombre cientifico
     *
     * @return "null value" si no se tiene ningun valor en el campo de busqueda, y retorna "ok" si el proceso
     * se llevó a cabo correctamente
     */
    public String actualizarListaOpciones(Object value, int opcion) 
    {
        this.listaResultados.clear();   //se deja vacia de nuevo la lista de resultados (para añadir los nuevos)
        if(value == null) //validacion de que se haya ingresado algun parametro de busqueda
        {
            return "null value";
        }

        boolean ingresarOpciones = true;
        ArrayList <String> lista = new ArrayList();
        switch(opcion)
        {
            case 1:
                if(value.toString().length()< 3)
                    ingresarOpciones = false;
                else
                    this.familias = familiaBean.recuperarFamilias(value.toString());
                lista = this.familias;
                break;
            case 2:
                if(value.toString().length()< 3)
                    ingresarOpciones = false;
                else
                    this.generos = generoBean.recuperarGeneros(value.toString());
                lista = this.generos;
                break;
            case 3:
                if(value.toString().length()< 3)
                    ingresarOpciones = false;
                else
                    this.nombresCientificos = ejm.recuperarNombresCientificos(value.toString());
                lista = this.nombresCientificos;
                break;
        }

        if(lista == null)
            lista = new ArrayList();

        //se convierte el valor ingresado como parametro de busqueda a mayusculas para realizar la busqueda
        String palabraBuscada = value.toString().toUpperCase(); 
        //recorre toda la lista de datos disponibles
        if(ingresarOpciones)
        for(int i = 0; i < lista.size(); i++)
        {
            String item = lista.get(i); //se obtiene el dato de la fila especifica
            //se busca si en el string que identifica el item (uppername -> parametro) existe la palabra buscada
            if (item.toUpperCase().startsWith(palabraBuscada))
            {
                //se añade a la lista mostrando el valor encontrado que contiene la lista
                this.listaResultados.add(new SelectItem(item, item)); 
            }
        }
        return "ok";
    }

    /**
     * Listener que se encarga de cambiar la lista de sugerencias de Familias cuando cambia el Input (campo de busqueda)
     * en la busqueda avanzada
     *
     * @param event
     * @return
     */
    public String actualizarListaOpcionesCampoFamilia(TextChangeEvent event) 
    {
        actualizarListaOpcionesFamilia(event.getNewValue());
        FacesContext.getCurrentInstance().renderResponse(); //despues de actulizar la  lista renderiza la respuesta
        return "ok";
    }

    public String actualizarListaOpcionesFamilia(Object value) 
    {
        this.listaResultadosFamilia.clear();   //se deja vacia de nuevo la lista de resultados (para añadir los nuevos)
        if(value == null) //validacion de que se haya ingresado algun parametro de busqueda
        {
            return "null value";
        }

        boolean ingresarOpciones = true;
        if(value.toString().length()< 3)
            ingresarOpciones = false;
        ArrayList <String> lista = familiaBean.recuperarFamilias(value.toString());

        if(lista == null)
            lista = new ArrayList();

        //se convierte el valor ingresado como parametro de busqueda a mayusculas
        String palabraBuscada = value.toString().toUpperCase();
        //recorre toda la lista de datos disponibles
        if(ingresarOpciones)
        for(int i = 0; i < lista.size(); i++)
        {
            String item = lista.get(i); //se obtiene el dato de la fila especifica
            //busca si en el string que identifica el item (uppername -> parametro) existe la palabra buscada
            if (item.toUpperCase().startsWith(palabraBuscada))
            {
                //se añade a la lista mostrando el valor encontrado que contiene la lista
                this.listaResultadosFamilia.add(new SelectItem(item, item)); 
            }
        }
        return "ok";
    }
    
    public String cambiarOpcion(ActionEvent event)
    {
        return "ok";
    }
    
    //Definicion de atributos de la clase
    int COLUMNAS_TABLA = 10;
    String valor;                   //UI element
    HtmlSelectOneRadio opcion;      //UI element    
    String familia;
    String genero;
    String nombreCientifico;
    String colectorPrincipal;
    String numeroColeccion;
    String codigoBarras;
    Integer pais;
    Integer departamento;
    Integer municipio;
    String ubicacion;
    String esp;                     //UI element
    String mensaje;
    String rutaImagenes;

    List<Ejemplar> ejemplares;
    List<Ejemplar> ejemplaresEspecie;
    GeneracionLista generaLista = null;

    /**
     * Metodo constructor de la clase ConsultaBean
     */
    public ConsultaBean()
    {
        generaLista = null;
        ejemplares = new ArrayList<Ejemplar>();
        familiaBean = new FamiliaBean();
        generoBean = new GeneroBean();
        ejm = new EjemplarBean();
        ResourceBundle rutas = ResourceBundle.getBundle(ConstantesStatic.PROPERTIES_RUTAS);
        rutaImagenes = rutas.getString("rutaImagenes");
    }

    /**
     * Metodo que realiza la busqueda basica y retorna los ejemplares hallados en la misma de acuerdo al
     * filtro de busqueda seleccionado y al valor ingresado como parametro
     * 
     * @param event
     * @return
     */
   public String consultarEjemplaresBasica(ActionEvent event)
    {
       int auxopcion = Integer.parseInt(this.getOpcion().getValue().toString());
       String mensaje = "";
       if(generaLista == null)
           generaLista = new GeneracionLista();
       
        try
        {
            if (auxopcion > 0)    //Si se ha seleccionado una opcion de busqueda
            {
                //Valida que se haya ingresado algun dato
                if (valor != null && !"".equals(valor))
                {
                    //Almacena los ejemplares obenidos de la busqueda basica en la lista ejemplares
                    ejemplares = generaLista.obtenerEjemplares(auxopcion, valor);
                    if(ejemplares.size() == 0)
                    {
                        mensaje = "No se encontraron registros en la busqueda";
                        JavascriptContext.addJavascriptCall(FacesContext.getCurrentInstance(),"mostrarMensajeBasica('"+mensaje+"');");
                        return "fail";
                    }
                    try
                    {
                        FacesContext.getCurrentInstance().getExternalContext().redirect("listarbusqueda.iface");
                        this.valor = "";

                        familia = "";
                        genero = "";
                        nombreCientifico = "";
                        colectorPrincipal = "";
                        numeroColeccion = "";
                        codigoBarras = "";
                        pais = null;
                        departamento = null;
                        municipio = null;
                        ubicacion = "";
                    }
                    catch (IOException ex)
                    {
                        mensaje = "Ha ocurrido un error al Realizar la busqueda";
                        JavascriptContext.addJavascriptCall(FacesContext.getCurrentInstance(),"mostrarMensajeBasica('"+mensaje+"');");
                    }
                    return "ok";
                }
                else
                    {
                        //mostrar mensaje
                        mensaje = "Por favor ingrese un parametro para la busqueda";
                        JavascriptContext.addJavascriptCall(FacesContext.getCurrentInstance(),"mostrarMensajeBasica('"+mensaje+"');");
                        return "fail";
                    }
            }

            else
                {
                    //mostrar mensaje
                    mensaje = "Debe seleccionar una opcion";
                    return "fail";
                }
            
            //mostrar mensajes al usuario cuando ocurra error
        }
        catch(NullPointerException e)
        {
            //mostrar mensaje
            mensaje = "No se encontro ningun ejemplar asociado al criterio de busqueda";
        }
       return "fail";
   }

    public String actualizarRadio(ActionEvent event)
    {
        return "ok";
    }

    /**
     * Metodo que realiza la busqueda avanzada y retorna los ejemplares hallados en la misma de acuerdo a los
     * valores ingresados en los campos de busqueda: familia, genero, nombre cientifico, colector principal,
     * numero coleccion, codigo de barras, ubicacion (pais, departamento, municipio)
     *
     * @param event
     * @return
     */
    public String consultarEjemplaresAvanzada(ActionEvent event)
    {
        if(generaLista == null)
           generaLista = new GeneracionLista();
        try
        {
            //Valida que se haya ingresado por lo menos un criterio de busqueda
            if (familia != null || genero != null || nombreCientifico != null || colectorPrincipal != null ||
                    numeroColeccion != null || codigoBarras != null || pais != null || departamento != null ||
                    municipio != null)
            {
                if (!"".equals(familia) || !"".equals(genero) || !"".equals(nombreCientifico) || 
                    !"".equals(colectorPrincipal) || !"".equals(numeroColeccion) ||
                    !"".equals(codigoBarras) || pais > 0 || departamento > 0 ||
                    municipio > 0)
                {
                    if(pais == null)
                        pais = 0;
                    if(departamento == null)
                        departamento = 0;
                    if(municipio == null)
                        municipio = 0;
                    //Almacena los ejemplares obtenidos de la busqueda avanzada en la lista ejemplares
                    ejemplares = generaLista.obtenerEjemplares(familia, genero, nombreCientifico, colectorPrincipal,
                    numeroColeccion, codigoBarras, pais, departamento, municipio);
                    if(ejemplares.size() == 0)
                    {
                        mensaje = "No se encontraron registros en la busqueda";
                        JavascriptContext.addJavascriptCall(FacesContext.getCurrentInstance(),"mostrarMensajeAvanzada('"+mensaje+"');");
                        return "no_ejemplares";
                    }
                    try
                    {
                        FacesContext.getCurrentInstance().getExternalContext().redirect("listarbusqueda.iface");
                        familia = "";
                        genero = "";
                        nombreCientifico = "";
                        colectorPrincipal = "";
                        numeroColeccion = "";
                        codigoBarras = "";
                        pais = null;
                        departamento = null;
                        municipio = null;
                        ubicacion = "";
                        valor = "";
                    }
                    catch (IOException ex)
                    {
                        mensaje = "No se encontraron registros en la busqueda";
                        JavascriptContext.addJavascriptCall(FacesContext.getCurrentInstance(),"mostrarMensajeAvanzada('"+mensaje+"');");
                    }
                }

                mensaje = "Los valores ingresados no son validos para realizar la busqueda";
                JavascriptContext.addJavascriptCall(FacesContext.getCurrentInstance(),"mostrarMensajeAvanzada('"+mensaje+"');");
            }

            mensaje = "Debe ingresar algun valor para la busqueda";
            JavascriptContext.addJavascriptCall(FacesContext.getCurrentInstance(),"mostrarMensajeAvanzada('"+mensaje+"');");
            return "ok";
        }
        catch (NullPointerException e)
        {
            mensaje = "No se encontro ningun ejemplar asociado al criterio de busqueda";
            JavascriptContext.addJavascriptCall(FacesContext.getCurrentInstance(),"mostrarMensajeAvanzada('"+mensaje+"');");
            return "fail";
        }
    }

    /**
     * Metodo que obtiene los ejemplares asociados a la misma especie
     * 
     * @param event
     */
    public void obtenerUbicacionEspecie(ActionEvent event)
    {
        try
        {
            //Valida que se haya ingresado algun dato para la busqueda por especie
            if (esp != null && !"".equals(esp))
            {
                //Almacena los ejemplares pertenecientes a la misma especie en la lista ejemplares
                ejemplaresEspecie = generaLista.obtenerUbicacionEspecie(esp);
            }

            else
            {
                mensaje = "Se requiere el nombre de la especie";
                return;
            }
        }
        catch(NullPointerException e)
        {
            mensaje = "No se encontro ningun ejemplar asociado a la misma especie";
        }
    }

    //Metodos get y set de los atributos de la clase
    public String getCodigoBarras() {
        return codigoBarras;
    }

    public void setCodigoBarras(String codigoBarras) {
        this.codigoBarras = codigoBarras;
    }

    public String getColectorPrincipal() {
        return colectorPrincipal;
    }

    public void setColectorPrincipal(String colectorPrincipal) {
        this.colectorPrincipal = colectorPrincipal;
    }

    public List<Ejemplar> getEjemplares() {
        return ejemplares;
    }

    public void setEjemplares(List<Ejemplar> ejemplares) {
        this.ejemplares = ejemplares;
    }

    public String getFamilia() {
        return familia;
    }

    public void setFamilia(String familia) {
        this.familia = familia;
    }

    public String getGenero() {
        return genero;
    }

    public void setGenero(String genero) {
        this.genero = genero;
    }

    public String getNombreCientifico() {
        return nombreCientifico;
    }

    public void setNombreCientifico(String nombreCientifico) {
        this.nombreCientifico = nombreCientifico;
    }

    public String getNumeroColeccion() {
        return numeroColeccion;
    }

    public void setNumeroColeccion(String numeroColeccion) {
        this.numeroColeccion = numeroColeccion;
    }

    public HtmlSelectOneRadio getOpcion() {
        return opcion;
    }

    public void setOpcion(HtmlSelectOneRadio opcion) {
        this.opcion = opcion;
    }

    public Integer getPais() {
        return pais;
    }

    public void setPais(Integer pais) {
        this.pais = pais;
    }

     public Integer getDepartamento() {
        return departamento;
    }

    public void setDepartamento(Integer departamento) {
        this.departamento = departamento;
    }

     public Integer getMunicipio() {
        return municipio;
    }

    public void setMunicipio(Integer municipio) {
        this.municipio = municipio;
    }

    public String getValor() {
        return valor;
    }

    public void setValor(String valor) {
        this.valor = valor;
    }

    public List<Ejemplar> getEjemplaresEspecie() {
        return ejemplaresEspecie;
    }

    public void setEjemplaresEspecie(List<Ejemplar> ejemplaresEspecie) {
        this.ejemplaresEspecie = ejemplaresEspecie;
    }

    public int getCOLUMNAS_TABLA() {
        return COLUMNAS_TABLA;
    }

    public void setCOLUMNAS_TABLA(int COLUMNAS_TABLA) {
        this.COLUMNAS_TABLA = COLUMNAS_TABLA;
    }

    public String getEsp() {
        return esp;
    }

    public void setEsp(String esp) {
        this.esp = esp;
    }

    public GeneracionLista getGeneraLista() {
        return generaLista;
    }

    public void setGeneraLista(GeneracionLista generaLista) {
        this.generaLista = generaLista;
    }

    public String getMensaje() {
        return mensaje;
    }

    public void setMensaje(String mensaje) {
        this.mensaje = mensaje;
    }

    public SelectInputText getCampoAutocompleta() {
        return campoAutocompleta;
    }

    public void setCampoAutocompleta(SelectInputText campoAutocompleta) {
        this.campoAutocompleta = campoAutocompleta;
    }

    public List<SelectItem> getListaResultados() {
        return listaResultados;
    }

    public void setListaResultados(List<SelectItem> listaResultados) {
        this.listaResultados = listaResultados;
    }

    public EjemplarBean getEjm() {
        return ejm;
    }

    public void setEjm(EjemplarBean ejm) {
        this.ejm = ejm;
    }

    public FamiliaBean getFamiliaBean() {
        return familiaBean;
    }

    public void setFamiliaBean(FamiliaBean familiaBean) {
        this.familiaBean = familiaBean;
    }

    public ArrayList<String> getFamilias() {
        return familias;
    }

    public void setFamilias(ArrayList<String> familias) {
        this.familias = familias;
    }

    public GeneroBean getGeneroBean() {
        return generoBean;
    }

    public void setGeneroBean(GeneroBean generoBean) {
        this.generoBean = generoBean;
    }

    public ArrayList<String> getGeneros() {
        return generos;
    }

    public void setGeneros(ArrayList<String> generos) {
        this.generos = generos;
    }

    public ArrayList<String> getNombresCientificos() {
        return nombresCientificos;
    }

    public void setNombresCientificos(ArrayList<String> nombresCientificos) {
        this.nombresCientificos = nombresCientificos;
    }

    public String getRutaImagenes() {
        return rutaImagenes;
    }

    public void setRutaImagenes(String rutaImagenes) {
        this.rutaImagenes = rutaImagenes;
    }

    public int getLimiteDatos() {
        return limiteDatos;
    }

    public void setLimiteDatos(int limiteDatos) {
        this.limiteDatos = limiteDatos;
    }

    public SelectInputText getCampoAutocompletaFamilia() {
        return campoAutocompletaFamilia;
    }

    public void setCampoAutocompletaFamilia(SelectInputText campoAutocompletaFamilia) {
        this.campoAutocompletaFamilia = campoAutocompletaFamilia;
    }

    public SelectInputText getCampoAutocompletaGenero() {
        return campoAutocompletaGenero;
    }

    public void setCampoAutocompletaGenero(SelectInputText campoAutocompletaGenero) {
        this.campoAutocompletaGenero = campoAutocompletaGenero;
    }

    public SelectInputText getCampoAutocompletaNomCientifico() {
        return campoAutocompletaNomCientifico;
    }

    public void setCampoAutocompletaNomCientifico(SelectInputText campoAutocompletaNomCientifico) {
        this.campoAutocompletaNomCientifico = campoAutocompletaNomCientifico;
    }

    public List<SelectItem> getListaResultadosFamilia() {
        return listaResultadosFamilia;
    }

    public void setListaResultadosFamilia(List<SelectItem> listaResultadosFamilia) {
        this.listaResultadosFamilia = listaResultadosFamilia;
    }

    public String getUbicacion() {
        return ubicacion;
    }

    public void setUbicacion(String ubicacion) {
        this.ubicacion = ubicacion;
    }    
}
